package com.myqf.d6_lambda_函数式接口_方法引用.monday.lambda.四个函数式接口;


/**
 * 作者：黎杭
 * 日期：2020/2/17
 */
public class Test {

    public static void main(String[] args) {
        // 向上转型安全
        Consumer1 consumer1 = new Consumer1Impl();// 其实就是这么玩的，但是这样写，不够简洁
        Consumer1 consumer2 = new Consumer2Impl();// 其实就是这么玩的，但是这样写，不够简洁
        // 这里不管你传什么，都没有关系，因为只在乎实现类里边覆写的方法主体才是有用的
        eat("消息1", consumer1);// 并不是把接口传进去，而是传的是一个接口的实现类的实例
        eat("消息2", consumer2);// 并不是把接口传进去，而是传的是一个接口的实现类的实例
        // 于是发现，这样写出不同的类名根本就没有意义，所以咱们能否省略写类名这个步骤？
        Consumer1 consumer11 = (Consumer1<String>) o -> System.err.println(o);// 这段代码实际上就是一个匿名内部类的 实例

        eat("消息3", o -> System.err.println(o));// 直接把实例丢进去
        // 现在大家在看。
        // consumer11 是一个没有名字的实现类 的实例，也就是说lambda表达式准确的说就是一个没有名字的类的实例
        // 其实Consumer1 的名字也是没有用的，因为我们不在乎你这个接口的名字，我们只在乎接口实现类覆写的方法主体
    }
    public static void eat(String msg, Consumer1<String> c) {
        // 这个方法实际上是指的是Consumer1 的实现类，也可以说是子类的实例在调用的方法
        // 其实这里叫多态
        // 接口是不能直接调用抽象方法的
        // 真正调用这个方法的，实际上指后边传来的实现类
        c.accept1(msg);// 只是叫一声，你该调用自己的accept1的方法了
    }


}
